#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
全局数据库Session管理模块

使用 SQLAlchemy + scoped_session 实现全局session管理
支持"一次构建，处处使用"的模式，避免session参数传递
"""

import os
import sys
import logging
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, scoped_session
from sqlalchemy.pool import QueuePool
from typing import Dict, Any

# 添加项目根目录到路径
project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
if project_root not in sys.path:
    sys.path.insert(0, project_root)

try:
    from src.utils.config import get_db_config
except ImportError:
    # 如果无法导入，使用默认配置
    def get_db_config():
        return {
            'host': os.getenv('DB_HOST', '127.0.0.1'),
            'port': int(os.getenv('DB_PORT', 3306)),
            'username': os.getenv('DB_USER', 'root'),
            'password': os.getenv('DB_PASSWORD', ''),
            'database': os.getenv('DB_NAME', 'tianyi_webdav')
        }

# 全局变量
_engine = None
_SessionFactory = None
_Session = None
_logger = logging.getLogger(__name__)

def _get_database_url(config: Dict[str, Any]) -> str:
    """获取数据库连接URL"""
    return f"mysql+pymysql://{config['username']}:{config['password']}@{config['host']}:{config['port']}/{config['database']}?charset=utf8mb4"

def init_global_session(config: Dict[str, Any] = None):
    """初始化全局session管理器"""
    global _engine, _SessionFactory, _Session
    
    if _Session is not None:
        # _logger.info("全局Session已经初始化，跳过重复初始化")
        return True
    
    try:
        # 获取配置
        db_config = config or get_db_config()
        database_url = _get_database_url(db_config)
        
        # 创建Engine（连接池）- 优化配置
        _engine = create_engine(
            database_url,
            poolclass=QueuePool,
            pool_size=5,           # 减少连接池大小，避免过多连接
            max_overflow=10,       # 减少溢出连接数
            pool_pre_ping=True,    # 每次从池中取连接时ping一下，避免使用已断开的连接
            pool_recycle=1800,     # 连接最大复用时间（30分钟），防止MySQL自动断开空闲连接
            pool_timeout=10,       # 获取连接的超时时间（秒）
            connect_args={
                'connect_timeout': 5,    # MySQL连接超时
                'read_timeout': 10,      # MySQL读取超时
                'write_timeout': 10,     # MySQL写入超时
                'charset': 'utf8mb4'
            },
            echo=False             # 是否打印SQL语句
        )
        
        # 创建session工厂
        _SessionFactory = sessionmaker(
            bind=_engine,
            autocommit=False,
            autoflush=False
        )
        
        # 使用scoped_session实现线程/协程安全的全局session
        _Session = scoped_session(_SessionFactory)
        
        _logger.info("全局Session管理器初始化成功")
        return True
        
    except Exception as e:
        _logger.error(f"全局Session管理器初始化失败: {str(e)}")
        return False

def get_session():
    """获取全局Session实例
    
    Returns:
        scoped_session: 线程安全的session实例
    """
    if _Session is None:
        _logger.warning("全局Session未初始化，尝试自动初始化")
        if not init_global_session():
            raise RuntimeError("全局Session初始化失败")
    
    return _Session

def get_engine():
    """获取全局Engine实例
    
    Returns:
        Engine: SQLAlchemy引擎实例
    """
    if _engine is None:
        _logger.warning("全局Engine未初始化，尝试自动初始化")
        if not init_global_session():
            raise RuntimeError("全局Session初始化失败")
    
    return _engine

def cleanup_session():
    """清理当前线程的session
    
    在Web应用中，通常在请求结束时调用此方法
    """
    if _Session is not None:
        _Session.remove()

def close_all_sessions():
    """关闭所有session和连接池
    
    通常在应用关闭时调用
    """
    global _engine, _SessionFactory, _Session
    
    if _Session is not None:
        _Session.remove()
        _Session = None
    
    if _engine is not None:
        _engine.dispose()
        _engine = None
    
    _SessionFactory = None
    _logger.info("全局Session管理器已关闭")

def test_connection() -> bool:
    """测试数据库连接"""
    try:
        from sqlalchemy import text
        session = get_session()
        # 执行简单查询测试连接
        session.execute(text("SELECT 1"))
        cleanup_session()
        _logger.info("数据库连接测试成功")
        return True
    except Exception as e:
        _logger.error(f"数据库连接测试失败: {str(e)}")
        return False

# 为了兼容性，提供一个Session别名
Session = get_session

def get_sqlalchemy_manager():
    """获取SQLAlchemy管理器实例"""
    return SQLAlchemyManager()

def get_db_session():
    """获取数据库会话（兼容性函数）"""
    return get_session()

class SQLAlchemyManager:
    """SQLAlchemy管理器类"""
    
    def __init__(self):
        self.engine = get_engine()
    
    def get_session(self):
        """获取数据库会话"""
        return get_session()
    
    def get_engine(self):
        """获取数据库引擎"""
        return self.engine
    
    def close_all_sessions(self):
        """关闭所有会话"""
        close_all_sessions()

if __name__ == "__main__":
    # 测试代码
    logging.basicConfig(level=logging.INFO)
    
    print("测试全局Session管理器...")
    
    # 初始化
    if init_global_session():
        print("✓ 全局Session初始化成功")
        
        # 测试连接
        if test_connection():
            print("✓ 数据库连接测试成功")
        else:
            print("✗ 数据库连接测试失败")
        
        # 测试获取session
        try:
            session = get_session()
            print(f"✓ 获取Session成功: {type(session)}")
            cleanup_session()
        except Exception as e:
            print(f"✗ 获取Session失败: {e}")
        
        # 清理
        close_all_sessions()
        print("✓ 清理完成")
    else:
        print("✗ 全局Session初始化失败")